Skip to content

Conversation

@digitalghost-dev
Copy link
Owner

@digitalghost-dev digitalghost-dev commented Dec 7, 2025

Summary by CodeRabbit

  • New Features

    • Async image loading with a visual spinner in the card viewer.
    • API helpers now return resource names alongside data for clearer responses.
  • Bug Fixes

    • Improved error handling and reporting across several commands.
  • Documentation

    • Added a Data Architecture section; README examples and badges updated and syntax fixed.
    • New test golden data for an ability.
  • Chores

    • Version bumped to v1.8.1 across build and packaging configs.
    • Project/config version and materialization settings updated.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 7, 2025

Walkthrough

Bumps project versioning to v1.8.1 across CI/release/packaging/docs; adds a generic FetchEndpoint[T] API fetch path and EndpointResource interface with GetResourceName() methods; refactors per-endpoint callers/tests to return a resource name; converts several commands to return errors instead of exiting; and adds async image loading with a spinner in the card viewer.

Changes

Cohort / File(s) Summary
Version & Packaging
\.github/workflows/ci.yml`, `.goreleaser.yml``, Dockerfile, ``nfpm.yaml``, ``testdata/main_latest_flag.golden``
Bumped version strings from v1.8.0 → v1.8.1 across CI, release linker flags, Docker build, packaging metadata, and golden output.
Documentation
README.md, card_data/README.md
README: updated badges and docker examples; card_data README: added Data Architecture section and fixed minor formatting.
DBT Configuration
card_data/pipelines/poke_cli_dbt/dbt_project.yml
Bumped dbt project version to 1.8.1, added models.poke_cli_dbt: materialized: table, removed on-run-end create_relationships() hook.
Generic API Refactor
connections/connection.go, connections/connection_test.go
Added EndpointResource interface and generic FetchEndpoint[T EndpointResource]; added package-level httpClient (30s); consolidated URL building, ApiCallSetup behavior and standardized error messages; per-endpoint helpers now return (resource, name, error) and tests updated.
Struct Accessors
structs/structs.go
Added GetResourceName() string methods for AbilityJSONStruct, ItemJSONStruct, MoveJSONStruct, PokemonJSONStruct, PokemonSpeciesJSONStruct, and TypesJSONStruct to satisfy EndpointResource.
Command Error Handling
cmd/ability/ability.go, cmd/item/item.go
Reworked command error paths to append error text to output and return (output, error) instead of calling os.Exit or printing and exiting.
Per-endpoint Call Sites
cmd/pokemon/pokemon.go, other callers of connections helpers
Updated callers to accept the additional returned resource-name string (often ignored as _); preserved prior control flow.
Image Viewer Async Loading
cmd/card/imageviewer.go, cmd/card/imageviewer_test.go
Introduced imageReadyMsg, fetchImageCmd, added Loading bool, Spinner spinner.Model, and ImageData string to ImageModel; Init/Update/View now handle spinner, async fetch, success/error states; tests adapted for loading/loaded flows.
Styling & Rendering
styling/styling.go, cmd/speed/speed.go
Replaced YellowAdaptive(s string) with Yellow lipgloss.Style and updated calls to use Yellow.Render(...); adjusted related imports/initialization.
Tests & Testdata
cmd/ability/ability_test.go, testdata/ability_poison_point.golden
Added test for poison-point ability and corresponding golden file; tests updated to handle new API return value and imageviewer behavior.

Sequence Diagram(s)

sequenceDiagram
  participant Caller as Command/Handler
  participant Fetch as FetchEndpoint[T]
  participant ApiSetup as ApiCallSetup
  participant HTTP as http.Client
  participant API as External API
  Caller->>Fetch: FetchEndpoint(endpoint, resourceName, baseURL, type)
  Fetch->>ApiSetup: ApiCallSetup(url, target)
  ApiSetup->>HTTP: Do(request)
  HTTP->>API: HTTP request
  API-->>HTTP: HTTP response (200/other)
  HTTP-->>ApiSetup: response
  ApiSetup->>ApiSetup: validate status, unmarshal into target
  alt success
    ApiSetup-->>Fetch: parsed resource
    Fetch-->>Caller: (resource, resource.GetResourceName(), nil)
  else failure
    ApiSetup-->>Fetch: error
    Fetch-->>Caller: (zero, "", error)
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Files needing extra attention:
    • connections/connection.go — generic implementation, URL construction, error message semantics, shared httpClient usage.
    • connections/connection_test.go — updated test cases for non-200 responses and name return values.
    • structs/structs.go — correctness of GetResourceName implementations.
    • cmd/card/imageviewer.go & tests — async command wiring, spinner lifecycle, and test expectations.
    • Review call sites across cmd/* to ensure the extra name return is handled intentionally.

Possibly related issues

Possibly related PRs

  • 1.7.3 #196 — Modifies the same dbt_project.yml (version bump, materialization, hook removal).
  • 1.7.4 #200 — Also changes the dbt project file and materialization settings.
  • 1.8.0 #203 — Related card UI/imageviewer updates and tests that align with async image loading changes.

Poem

🐰 A tiny hop, a version spun,
From .8.0 to .8.1!
FetchEndpoint fetches, names returned,
Spinners whirl while images are learned—
Errors now come back, not exit-run—hooray, refactor fun! 🎉

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.13% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title '1.8.1' is vague and generic, using only a version number without describing what changes are being made. Provide a descriptive title that explains the purpose of the version bump, such as 'Bump version to 1.8.1' or 'Release v1.8.1 with dbt configuration updates'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 1.8.1

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link

codecov bot commented Dec 7, 2025

Codecov Report

❌ Patch coverage is 70.65217% with 27 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
structs/structs.go 0.00% 12 Missing ⚠️
cmd/card/imageviewer.go 69.44% 7 Missing and 4 partials ⚠️
cmd/ability/ability.go 60.00% 2 Missing ⚠️
cmd/item/item.go 0.00% 2 Missing ⚠️
Files with missing lines Coverage Δ
cmd/pokemon/pokemon.go 88.27% <100.00%> (ø)
cmd/speed/speed.go 40.00% <100.00%> (ø)
connections/connection.go 91.11% <100.00%> (-0.56%) ⬇️
styling/styling.go 100.00% <ø> (+3.27%) ⬆️
cmd/ability/ability.go 75.00% <60.00%> (+6.25%) ⬆️
cmd/item/item.go 94.33% <0.00%> (+3.43%) ⬆️
cmd/card/imageviewer.go 77.08% <69.44%> (-22.92%) ⬇️
structs/structs.go 0.00% <0.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
cmd/speed/speed.go (1)

264-267: Inconsistent error handling: log.Fatalf vs returning errors.

Other strconv.Atoi conversions in this function (lines 276, 281, 285, 290) return errors, but this one calls log.Fatalf, which terminates the program abruptly. This is inconsistent and prevents proper error propagation.

 	speedStageInt, err := strconv.Atoi(pokemon.SpeedStage)
 	if err != nil {
-		log.Fatalf("Invalid SpeedStage: %v", err)
+		return "", fmt.Errorf("invalid SpeedStage: %w", err)
 	}
🧹 Nitpick comments (7)
cmd/ability/ability_test.go (1)

4-6: Good new test for hyphenated ability; consider asserting errors as well

  • Importing os and using os.Args to simulate CLI input is fine here, and the new "poison-point" case wired to ability_poison_point.golden gives nice coverage for special characters in API calls.
  • As a follow-up, since the table already defines wantError, you might eventually extend the loop to also assert on the error returned from AbilityCommand() (especially for the misspelled-ability case), rather than discarding it with output, _ := AbilityCommand().

No blockers for this PR; just a potential future tightening of the tests.

Also applies to: 45-49, 52-61

card_data/README.md (1)

6-25: Data architecture section is clear; optional wording polish

The new Data Architecture section is informative and reads well. If you want to tighten the wording in step 7, you could adopt the shorter phrasing suggested by the style check:

-7. Users are then able to query the `pokeapi.co` or supabase APIs for either video game or trading card data, respectively.
+7. Users can then query the `pokeapi.co` or Supabase APIs for either video game or trading card data, respectively.

Purely stylistic; no need to block on this.

cmd/card/imageviewer_test.go (1)

135-153: Consider adding test for error path.

There's no test for when imageReadyMsg contains an error. Consider adding a test to verify that Update correctly sets Error and clears ImageData when the fetch fails.

func TestImageModel_Update_ImageReadyError(t *testing.T) {
	model := ImageRenderer("Charizard", "http://example.com/charizard.png")
	expectedErr := fmt.Errorf("failed to fetch image")

	msg := imageReadyMsg{err: expectedErr}
	newModel, cmd := model.Update(msg)

	if cmd != nil {
		t.Error("Update with error imageReadyMsg should return nil command")
	}

	updatedModel := newModel.(ImageModel)
	if updatedModel.Loading {
		t.Error("Update with error should set Loading to false")
	}
	if updatedModel.Error == nil {
		t.Error("Update with error should set Error")
	}
	if updatedModel.ImageData != "" {
		t.Error("Update with error should clear ImageData")
	}
}
cmd/speed/speed.go (1)

7-7: Remove unused import after fixing error handling.

After fixing the log.Fatalf issue, the log import will become unused and should be removed.

connections/connection_test.go (3)

235-235: Use assert.Empty for consistency.

For consistency with the linter's recommendations, use assert.Empty here as well.

-		assert.Equal(t, "", name, "Expected empty name string on error")
+		assert.Empty(t, name, "Expected empty name string on error")

288-288: Use assert.Empty for consistency.

Same recommendation for consistency.

-		assert.Equal(t, "", name, "Expected empty name string on error")
+		assert.Empty(t, name, "Expected empty name string on error")

326-326: Use assert.Empty for consistency.

Same recommendation for consistency.

-		assert.Equal(t, "", name, "Expected empty name string on error")
+		assert.Empty(t, name, "Expected empty name string on error")
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d55869a and a7bedce.

📒 Files selected for processing (20)
  • .github/workflows/ci.yml (1 hunks)
  • .goreleaser.yml (1 hunks)
  • Dockerfile (1 hunks)
  • README.md (2 hunks)
  • card_data/README.md (1 hunks)
  • card_data/pipelines/poke_cli_dbt/dbt_project.yml (1 hunks)
  • cmd/ability/ability.go (3 hunks)
  • cmd/ability/ability_test.go (2 hunks)
  • cmd/card/imageviewer.go (2 hunks)
  • cmd/card/imageviewer_test.go (2 hunks)
  • cmd/item/item.go (1 hunks)
  • cmd/pokemon/pokemon.go (1 hunks)
  • cmd/speed/speed.go (2 hunks)
  • connections/connection.go (3 hunks)
  • connections/connection_test.go (8 hunks)
  • nfpm.yaml (1 hunks)
  • structs/structs.go (1 hunks)
  • styling/styling.go (1 hunks)
  • testdata/ability_poison_point.golden (1 hunks)
  • testdata/main_latest_flag.golden (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (6)
cmd/card/imageviewer.go (3)
cmd/search/search.go (1)
  • Model (48-56)
cmd/card/cardinfo.go (1)
  • CardImage (23-58)
styling/styling.go (2)
  • Red (14-14)
  • Yellow (16-16)
cmd/ability/ability_test.go (1)
cmd/utils/golden.go (1)
  • LoadGolden (10-46)
cmd/speed/speed.go (1)
styling/styling.go (1)
  • Yellow (16-16)
connections/connection.go (1)
styling/styling.go (2)
  • ErrorBorder (34-36)
  • ErrorColor (33-33)
cmd/ability/ability.go (3)
connections/connection.go (2)
  • AbilityApiCall (82-84)
  • APIURL (17-17)
styling/styling.go (1)
  • ColoredBullet (17-19)
flags/abilityflagset.go (1)
  • PokemonAbilitiesFlag (31-66)
cmd/pokemon/pokemon.go (1)
connections/connection.go (2)
  • PokemonSpeciesApiCall (98-100)
  • APIURL (17-17)
🪛 GitHub Actions: Lint
connections/connection_test.go

[error] 121-121: golangci-lint: empty: use assert.Empty (testifylint) instead.

🪛 GitHub Check: linter
connections/connection_test.go

[failure] 121-121:
empty: use assert.Empty (testifylint)


[failure] 159-159:
empty: use assert.Empty (testifylint)


[failure] 197-197:
empty: use assert.Empty (testifylint)

🪛 LanguageTool
card_data/README.md

[style] ~25-~25: As a shorter alternative for ‘able to’, consider using “can then”.
Context: ...a Supabase production schema. 7. Users are then able to query the pokeapi.co or supabase APIs...

(BE_ABLE_TO)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: tests
🔇 Additional comments (35)
nfpm.yaml (1)

4-4: Version bump in nfpm manifest looks consistent

version: "v1.8.1" aligns with the release bump in the rest of the PR. No other packaging changes here.

.goreleaser.yml (1)

17-17: GoReleaser ldflags updated to embed v1.8.1

The linker flag now sets main.version=v1.8.1, which matches the new release version used elsewhere.

testdata/main_latest_flag.golden (1)

5-5: Confirm --latest golden vs new binary version

This golden expects Latest available release to render v1.8.0, while this PR bumps the tool itself to v1.8.1. If --latest is meant to report the latest GitHub release (not the running binary’s version), this is fine; otherwise, it may need to be updated to v1.8.1.

Please confirm the intended semantics of the --latest flag and adjust the golden if necessary.

testdata/ability_poison_point.golden (1)

1-3: New Poison Point golden file is well-formed

The golden output for “Poison Point” matches the existing style (title + bullet details) and provides clear effect text. Looks ready to use in tests.

card_data/pipelines/poke_cli_dbt/dbt_project.yml (1)

2-2: dbt project version and materialization update look good

  • Project version: '1.8.1' matches the overall release bump.
  • +materialized: table under models.poke_cli_dbt is valid dbt config for materializing those models as tables.

No further changes needed here.

Also applies to: 21-21

cmd/card/imageviewer.go (7)

3-8: LGTM!

The imports are appropriate for the new async image loading feature with spinner support.


10-22: LGTM!

The ImageModel struct is well-designed with clear separation of concerns between state fields (Loading, Error, ImageData) and configuration (CardName, ImageURL, Spinner). The private imageReadyMsg type correctly encapsulates the async fetch result.


24-33: LGTM!

The async command correctly wraps the CardImage call and properly propagates both success and error states via imageReadyMsg.


35-40: LGTM!

Correct use of tea.Batch to start both the spinner animation and the image fetch concurrently.


42-65: LGTM!

The Update method correctly handles all message types with proper state transitions. The error/success handling in imageReadyMsg properly clears the opposite state to maintain consistency.


67-77: LGTM!

The View method correctly prioritizes states: loading → error → data. The spinner feedback during loading provides good UX.


79-90: LGTM!

The ImageRenderer factory function correctly initializes the model in a loading state with the spinner configured and ready.

cmd/card/imageviewer_test.go (8)

10-17: LGTM!

Test correctly verifies that Init() returns a non-nil command, which is expected since it batches the spinner tick and fetch commands.


19-52: LGTM!

Tests correctly verify that ESC and Ctrl+C trigger quit commands while maintaining the model type.


54-66: LGTM!

Correctly verifies that non-quit keys don't trigger any commands.


68-81: LGTM!

Good test coverage for the loading state view, verifying both non-empty output and presence of the card name.


83-97: LGTM!

Correctly verifies that when loaded, View() returns the image data directly.


99-112: LGTM!

Good edge case coverage for empty image data scenario.


114-133: LGTM!

Comprehensive test for the ImageRenderer factory function, verifying all essential initial state values.


135-153: LGTM!

Excellent test for the async image fetch success path, verifying proper state transitions when imageReadyMsg is received.

.github/workflows/ci.yml (1)

33-33: LGTM!

Version bump to v1.8.1 is consistent with the PR objectives and will propagate correctly through all workflow jobs.

Dockerfile (1)

11-11: LGTM!

Version bump in ldflags is consistent with other version updates in this PR.

cmd/item/item.go (1)

51-55: LGTM!

Good refactor to return errors instead of exiting directly. This improves testability and allows callers to handle errors appropriately while still preserving the error message in the output for user display.

cmd/speed/speed.go (1)

308-319: LGTM!

The styling updates correctly use the new Yellow.Render() method, consistent with the refactored styling API.

cmd/pokemon/pokemon.go (1)

80-84: LGTM!

The change correctly handles the updated PokemonSpeciesApiCall signature that now returns an additional resource name string. Discarding it with _ is appropriate since the name isn't needed in this context.

cmd/ability/ability.go (3)

53-58: LGTM!

The error handling improvement correctly returns both the accumulated output and the error, allowing callers to access any partial output before the failure occurred.


60-64: LGTM!

Consistent error handling pattern that appends the error to output before returning.


97-101: LGTM!

The formatting change to use fmt.Sprintf is cleaner and more consistent.

structs/structs.go (1)

3-25: LGTM!

The GetResourceName() accessor methods correctly implement the EndpointResource interface required by the new generic FetchEndpoint function. Using value receivers for these simple getters is appropriate.

styling/styling.go (1)

12-16: LGTM!

The refactoring from YellowAdaptive function to a Yellow style variable is cleaner and more consistent with how other styles are defined in this file. The adaptive color behavior is preserved.

connections/connection.go (3)

19-19: LGTM!

Using a shared httpClient with a 30-second timeout enables connection reuse and prevents resource leaks from creating new clients per request.


65-67: LGTM!

Adding the non-200 status code check ensures API errors are properly detected and reported instead of attempting to parse error responses as valid JSON.


82-104: LGTM!

The per-endpoint API call functions now cleanly delegate to the generic FetchEndpoint, eliminating code duplication while maintaining the same public API signatures.

connections/connection_test.go (2)

62-87: LGTM!

Good addition of comprehensive test coverage for non-200 HTTP status codes. The table-driven test approach is clean and covers multiple failure scenarios.


244-275: LGTM!

The expanded TestTypesApiCall with proper struct initialization and name verification provides good coverage for the updated API signature.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
connections/connection_test.go (1)

244-275: TypesApiCall success test exercises nested payload realistically

The TypesApiCall success subtest builds a representative TypesJSONStruct (including nested Pokemon entries) and asserts both the struct and returned name, which should catch regressions in JSON wiring and naming behavior. If you later add more type fixtures, consider extracting a small helper to construct these structs to keep the test focused on behavior rather than struct literal noise.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a7bedce and ca27efe.

📒 Files selected for processing (1)
  • connections/connection_test.go (8 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
connections/connection_test.go (2)
connections/connection.go (7)
  • ApiCallSetup (44-80)
  • AbilityApiCall (82-84)
  • ItemApiCall (86-88)
  • MoveApiCall (90-92)
  • PokemonApiCall (94-96)
  • TypesApiCall (102-104)
  • PokemonSpeciesApiCall (98-100)
structs/structs.go (6)
  • AbilityJSONStruct (28-60)
  • ItemJSONStruct (85-107)
  • MoveJSONStruct (110-141)
  • PokemonJSONStruct (144-194)
  • TypesJSONStruct (221-261)
  • PokemonSpeciesJSONStruct (197-218)
🔇 Additional comments (3)
connections/connection_test.go (3)

7-7: Strong coverage for non‑200 ApiCallSetup responses

The table‑driven subtest across multiple non‑200 status codes plus explicit status‑code matching via strconv.Itoa gives good regression coverage for this path; the added strconv import is appropriate and used correctly.

Also applies to: 62-87


117-125: Consistent empty‑name and error semantics across API failure paths

Capturing name from each *ApiCall and asserting the zero‑value struct, empty name, and the styled, entity‑specific error messages keeps all endpoints’ failure behavior consistent and matches the new FetchEndpoint contract.

Also applies to: 155-163, 193-201, 231-239, 284-292, 322-330


308-313: PokemonSpeciesApiCall success path updated correctly for name return

Updating the Pokémon species test to use the three‑value return and explicitly assert the species name alongside the struct aligns this test with the other endpoint helpers and the new API surface.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
cmd/card/imageviewer_test.go (2)

84-91: Strict equality on loaded view is acceptable but may be brittle

Right now View() returning exactly ImageData makes this assertion correct. If you later prepend/append metadata (card name, headers, etc.), this test will break; consider loosening to a containment or prefix check if you expect that evolution.


136-153: imageReadyMsg test exercises the full loading→loaded transition

This neatly covers clearing Loading and setting ImageData. One minor style tweak you might consider: avoid a potential panic by using the checked assertion pattern:

-	updatedModel := newModel.(ImageModel)
+	updatedModel, ok := newModel.(ImageModel)
+	if !ok {
+		t.Fatalf("Update should return ImageModel, got %T", newModel)
+	}

Functionally everything is correct as‑is; this just improves failure diagnostics.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ca27efe and ead7b3f.

📒 Files selected for processing (3)
  • README.md (2 hunks)
  • cmd/card/imageviewer_test.go (2 hunks)
  • styling/styling.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • styling/styling.go
🧰 Additional context used
🧬 Code graph analysis (1)
cmd/card/imageviewer_test.go (1)
cmd/card/imageviewer.go (2)
  • ImageRenderer (79-90)
  • ImageModel (10-17)
🔇 Additional comments (8)
README.md (2)

5-5: Version bumps and bracket syntax fix look good.

The docker image size badge (line 5) and both docker run examples (lines 98, 102) are now consistently updated to v1.8.1. The bracket syntax has also been corrected from [subcommand] flag] to [subcommand] [flag], fixing the previous typo flagged in review.

Also applies to: 98-98, 102-102


32-32: Verify demo GIF version consistency.

Line 32 still references poke-cli-v1.8.0.gif, while all other docker/version references in the README have been bumped to v1.8.1. Confirm whether a v1.8.1 demo GIF asset exists and should be referenced here, or if the v1.8.0 GIF is intentionally retained.

cmd/card/imageviewer_test.go (6)

3-9: Imports look appropriate for new tests

strings for substring checks and the spinnerpkg alias for TickMsg keep the tests readable and focused; nothing to change here.


12-16: Init test correctly guards async startup behavior

Asserting that Init() returns a non‑nil command (without executing it) is a good, non‑flaky way to ensure the spinner+fetch startup path doesn’t regress to a no‑op.


69-82: Loading view coverage is well targeted

Checking that View() is non‑empty and contains the card name while loading is a solid assertion that avoids brittle coupling to spinner frame output. No changes needed.


100-112: Empty view semantics are clearly defined

Asserting that View() returns an empty string when both ImageURL and ImageData are empty gives a precise contract for the “no image” state; the test looks good.


115-132: ImageRenderer initialization test matches the model contract

Verifying CardName, ImageURL, Loading == true, and empty ImageData captures the key guarantees of ImageRenderer; this should catch most accidental constructor regressions.


156-173: Spinner tick handling test is aligned with the Update logic

Constructing a tick message via msg := model.Spinner.Tick() and passing it through Update is an appropriate way to exercise the spinner‑tick branch and assert that a follow‑up command is returned while preserving the ImageModel type. No issues here.

@coderabbitai coderabbitai bot mentioned this pull request Jan 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants